

function $H(o){
	return new Hash(o);
}

function Hash(o){
	if(o){
		for(var s in o){
			this[s] = o[s];
			this.length++;
		}
	}
	this.watch("length",function(n,ov,nv){
		return this.keys().length;
	});
}

Hash.prototype = {
	constructor:Hash,
	length:0,
	
	toString:function(){
		return "Hash";
	},
	
	keys:function(h){
		var k=[], s="";
		for(s in this){
			if(!this.constructor.prototype.hasOwnProperty(s)){
				k[k.length] = s;
			}
		}
		return k;
	},
	
	values:function(h){
		var v=[], s="";
		for(s in this){
			if(!this.constructor.prototype.hasOwnProperty(s)){
				v[v.length] = this[s];
			}
		}
		return v;
	},
	
	toQueryString:function(){
		var a,s="",amp="",v="";
		for(a in this){
			if(this[a]&&!this.constructor.prototype.hasOwnProperty(a)){
				if(this[a].constructor==Array){
					var r = [];
					this[a].forEach(function(s,i){
						r[i] = encodeURIComponent(s);
					},this[a]);
					v = a + "=" + r.join(",");
				}else{
					v = a + "=" + encodeURIComponent(this[a]||"");
				}
				s += amp + v;
				amp="&";
			}
		}
		return s;
	},
	
	append:function(a,v){
		if(typeof a == "object"){
			for(var s in a){
				this[s]=a[s];
			}
		}else{
			if(!this.constructor.prototype.hasOwnProperty(a)){
				this[a]=v;
			}
		}
		return this.length;
	},
	
	remove:function(a){
		if(!this.constructor.prototype.hasOwnProperty(a)){
			delete this[a];
		}
		return this.length;
	},
	
	indexOf:function(str, startIndex){
		if(!str)return -1;
		if(!startIndex)startIndex=0; 
		var s,i=0;
		for(s in this){
			if(!this.constructor.prototype.hasOwnProperty(s)){
				if(str === this[s])return i;
				i++;
			}
		};
		return -1;
	},
	
	lastIndexOf:function(str, startIndex){
		if(!str)return -1;
		var keys=this.keys();
		if(!startIndex){startIndex=keys.length-1};
		for(var i=startIndex,o;o=this[(keys[i])];i++){
			if(str === o)return i;
		}
		
		return -1;
	},
	/* http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:forEach */
	forEach:function(callback, scope){
		if(typeof(callback)!="function"){ return false; };
		if(!scope){scope=window;};
		var s,i=0;
		for(s in this){
			if(!this.constructor.prototype.hasOwnProperty(s)){
				callback.apply(scope,s,this[s],i,this)
				i++;
			}
		}
	},
	/* http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:filter */
	filter:function(callback, scope){
		if(typeof(callback)!="function"){ return false; };
		if(!scope){ scope = window; };
		var r=new Hash(),s;
		for(s in this){
			if(!this.constructor.prototype.hasOwnProperty(s)){
				if(callback.call(scope,s,this[s],r.length,this)){
					r[s]=this[s];
					r.length++;
				}
			}
		};
		return r;
	},
	/* http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:every */
	every:function(callback, scope){
		if(typeof(callback)!="function"){ return false; };
		if(!scope){scope=window};
		var s,i=0;
		for(s in this){
			if(!this.constructor.prototype.hasOwnProperty(s)){
				if(!callback.call(scope,s,this[s],i,this))
					return false;
				i++;
			}
		};
		return true;
	},
	/* http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:some */
	some:function(callback, scope){
		if (typeof(callback)!="function"){return false;}
		var s,i=0;
		for(s in this){
			if(!this.constructor.prototype.hasOwnProperty(s)){
				if(callback.call(scope,s,this[s],i,this))
					return true;
				i++;
			}
		}
		return false;
	},
	/* http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:map */
	map:function(callback, scope){
		if(typeof(callback)!="function"){ return false; };
		if(!scope){scope=window};
		var r=new Hash();
		for(var s in this){
			if(!this.constructor.prototype.hasOwnProperty(s)){
				r[s] = callback.call(scope,s,this[s],r.length,this);
				r.length++;
			}
		};
		return r;
	}
	
	
}
